Preserve correctness of import.meta.url in bundled modules.#300
Preserve correctness of import.meta.url in bundled modules.#300
import.meta.url in bundled modules.#300Conversation
…de corrected URL.
… lerna bootstrap needed to do after I added acorn-import-meta.
|
Fixes #294 |
| const aUrl = analyzer.resolveUrl('a.js')!; | ||
| const bUrl = analyzer.resolveUrl('subfolder/b.js')!; | ||
| const cUrl = analyzer.resolveUrl('c.js')!; | ||
| const dUrl = analyzer.resolveUrl('d.js')!; |
There was a problem hiding this comment.
No, thanks! I was adding another test case and then gave up; forgot that was there. Removed.
packages/bundler/src/es6-rewriter.ts
Outdated
| moduleFile: babel.File, | ||
| relativeUrl: FileRelativeUrl): babel.File { | ||
| // Generate a stand-in for any local references to import.meta... | ||
| // const __bundledImportMeta = {...__importMeta, url: __bundledImportURL}; |
There was a problem hiding this comment.
I previously had a local variable stand-in just for import.meta that is now gone. Old comment. Fixed to import.meta! Thanks!
packages/bundler/src/es6-rewriter.ts
Outdated
| traverse(newModuleFile, { | ||
| noScope: true, | ||
| MetaProperty: { | ||
| enter(path: NodePath) { |
There was a problem hiding this comment.
Can avoid the cast below by doing: enter(page: NodePath<babel.MetaProperty>) {
There was a problem hiding this comment.
AH! Thanks! I have several of these in bundler code to fix! Will do now.
packages/bundler/src/es6-rewriter.ts
Outdated
| // URL has changed as a result of bundling. | ||
| const relativeUrl = | ||
| ensureLeadingDot(this.bundler.analyzer.urlResolver.relative( | ||
| this.bundle.url, id as ResolvedUrl)); |
There was a problem hiding this comment.
Is the cast of id needed? It looks like it's a ResolvedUrl already
There was a problem hiding this comment.
You're right. Fixed.
| ensureLeadingDot(this.bundler.analyzer.urlResolver.relative( | ||
| this.bundle.url, id as ResolvedUrl)); | ||
| const newAst = this._rewriteImportMetaToBundleMeta( | ||
| document.parsedDocument.ast as babel.File, relativeUrl); |
There was a problem hiding this comment.
We could put this constraint into the type system if we added a type checking function that checks that document is a Document<ParsedJavascriptDocument>
There was a problem hiding this comment.
You're right and in fact this code probably should have more guarantees/verification of the type of document it is loading anyways. I'll add a TODO here for this.
packages/bundler/src/es6-rewriter.ts
Outdated
| // Generate a stand-in for any local references to import.meta... | ||
| // const __bundledImportMeta = {...__importMeta, url: __bundledImportURL}; | ||
| const bundledImportMetaName = '__bundledImportMeta'; | ||
| const bundledImportMetaDeclaration = |
There was a problem hiding this comment.
Could maybe use the @babel/template ast template string literal tag here instead of building it manually with the API? (Example: https://github.com/Polymer/tools/blob/master/packages/build/src/babel-plugin-dynamic-import-amd.ts#L64)
There was a problem hiding this comment.
I love this idea. I even made a personal TODO note earlier today "Look up to see if there's a template string builder that would make this code cleaner."
I would like to consider bringing that approach to all of the ast production in bundler, but I'm going to hold off on a separate PR to bring that machinery in here. Adding TODO. It's a great idea and would make this code a lot better.
I should note that as of right now though, Bundler does not have any babel parsing in it and relies purely on Analyzer. Use of the template literal stuff would essentially require ensuring I either find a nice way to clone the Analyzer's babel parsing stack or rebuild it locally.
packages/bundler/src/es6-rewriter.ts
Outdated
| babel.identifier('import'), babel.identifier('meta'))), | ||
| babel.objectProperty( | ||
| babel.identifier('url'), | ||
| babel.newExpression( |
There was a problem hiding this comment.
We want to get the .href property of this new url, as import.meta.url is a string
There was a problem hiding this comment.
DERP! Really good catch. Fixed.
…ter-the-fact casting.
…arsedJavascriptDocument> verification and add typings to its ast.
|
Awww nuts. Something probably in the package-lock has updated causing something to break during gulp-typescript... https://ci.appveyor.com/project/Polymer/tools/build/1.0.858#L127 |
|
Bunch of things like |
|
Ah this failure is unrelated to branch. Created a new PR to start to fix the TS errors related to updating package locks at #309 |
| // Generate a stand-in for any local references to import.meta... | ||
| // const __bundledImportMeta = {...import.meta, url: __bundledImportURL}; | ||
| // TODO(usergenic): Consider migrating this AST production mishmash into the | ||
| // `ast` tagged template literal available like this: |
There was a problem hiding this comment.
+1. Much easier to read and write.
| // TODO(usergenic): Consider migrating this AST production mishmash into the | ||
| // `ast` tagged template literal available like this: | ||
| // https://github.com/Polymer/tools/blob/master/packages/build/src/babel-plugin-dynamic-import-amd.ts#L64 | ||
| const bundledImportMetaName = '__bundledImportMeta'; |
There was a problem hiding this comment.
We should generate this name to be conflict free with identifiers at import.meta use sites.
| babel.newExpression( | ||
| babel.identifier('URL'), | ||
| [ | ||
| // |
There was a problem hiding this comment.
remove? Or if it's for formatting, move to previous line?
There was a problem hiding this comment.
clang-format went crazy so I put this in here to get it to behave. I can annotate further. This of course goes away after I switch to ast template literal...
| babel.identifier('href'))) | ||
| ])) | ||
| ]); | ||
| const newModuleFile = clone(moduleFile); |
There was a problem hiding this comment.
why do you have to clone it?
There was a problem hiding this comment.
Because I modify in-place from document returned by analyzer and I'm trying to be a good citizen.
There was a problem hiding this comment.
+1. Modifying documents returned by analyzer will lead to the worst kind of weird bugs with spooky action at a distance.
packages/bundler/src/es6-rewriter.ts
Outdated
| return; | ||
| } | ||
| const bundledImportMeta = babel.identifier(bundledImportMetaName); | ||
| rewriteObject(metaProperty, bundledImportMeta); |
There was a problem hiding this comment.
use path.replaceWith instead?
There was a problem hiding this comment.
Okay. That makes sense here. Replace'd
| babel.identifier('href'))) | ||
| ])) | ||
| ]); | ||
| const newModuleFile = clone(moduleFile); |
There was a problem hiding this comment.
+1. Modifying documents returned by analyzer will lead to the worst kind of weird bugs with spooky action at a distance.
|
I'm seeing this transform present on the es6-bundled build output which doesn't make since it uses const bundledImportMeta = { ...import.meta,
url: new URL('...', import.meta.url).href
}; |
Note that in the case where an imported module's URL is identical to the bundle URL, no modification to the module code is needed before bundling it, but for all other cases where
import.metaoccurs somewhere in the document contents, we construct a module-scoped stand-in variable and swap other references to import.meta to use the stand-in, which is declared as an object-literal like{...import.meta, url: new URL(relativeUrlToModule, import.meta.url)}.